﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RRRSRoguelike.Entities;
using System.Threading;
using RRRSRoguelike.Managers;
using System.Drawing;
using System.Reflection;

namespace RRRSRoguelike.Helpers.Visualizer
{
    public class Visualizer
    {

        #region variables
        //Where to start drawing dungeon 0,0
        public Point StartPoint;

        public Camera Camera;

        public Layer layer;

        Player player = DungeonManager.Instance.CreatureManager.Player;

        #endregion

        #region constructors
        public Visualizer()
        {
            //Sets TopLeft of dungeon centered in console.
            StartPoint.X = Console.WindowWidth / 2 - Constants.DungeonWidth / 2;
            //StartPointY = Console.WindowHeight / 2 - Constants.DungeonHeight / 2 -1;
            StartPoint.Y =5;

            Camera = new Camera(Constants.DungeonWidth, Constants.DungeonHeight);
            layer = new Layer();
        }
        #endregion

        #region methods
        public static Point GetScreenCenter() 
        {
            return new Point(Console.WindowWidth / 2, Constants.DungeonHeight / 2);
        }

        public static int GetScreenWidth()
        {
            return Console.WindowWidth;
        }

        public static int GetScreenHeight()
        {
            return Console.WindowHeight;
        }

        public void Visualize(DungeonLevel dungeonLevel, bool drawPanel)
        {
            //Console.Clear();
            //Repeating this makes sure the console has not been resized.
            GameManager.SetConsoleSize(Constants.ConsoleWidth, Constants.ConsoleHeight);
            
            
            Draw(dungeonLevel, new Point(StartPoint.X, StartPoint.Y+1));

        }

        /// <summary>
        /// Wraps the console write line should make it easier to port later.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="color"></param>
        public static void WriteLine(string text, ConsoleColor color = ConsoleColor.White)
        {
            Console.ForegroundColor = color;
            Console.WriteLine(text);   
        }

        /// <summary>
        /// Uses the SetCursorPosition to place text.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="position"></param>
        public static void WriteLine(string text, Point position, ConsoleColor color = ConsoleColor.White) 
        {
            if (position.X < Console.WindowWidth && position.Y < Console.WindowHeight)
            {
                Console.SetCursorPosition(position.X, position.Y);

                WriteLine(text, color);
            }
        }

        public static void WriteMultiLine(string text, Point position, ConsoleColor color = ConsoleColor.White,StringSplitOptions options = StringSplitOptions.None)
        {
            string[] lineArray = text.Split("\r\n".ToArray(), options);


            foreach (string s in lineArray)
            {
                if (s != "")
                {
                    WriteLine(s, position, color);
                    position.Y++;
                }
            }
        }

        public static void WriteLine(DungeonSquare dungeonSquare, Point position)
        {
            Console.SetCursorPosition(position.X, position.Y);
            WriteLine(dungeonSquare.character, dungeonSquare.color);
        }

        /// <summary>
        /// Accepts text and a width adds spaces to text to centralize.
        /// Text should be one line and shorter than width, otherwise trims to fit one line.
        /// </summary>
        /// <param name="text">one line of text less than width</param>
        /// <param name="width">width of line in characters</param>
        /// <returns>a centralized text or trimmed text</returns>
        public static string CentralizeText(string text, int width)
        {
            //Centralize
            if (text.Length < width)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append(' ', (width - text.Length) / 2);
                sb.Append(text);
                sb.Append(' ', (width - text.Length) / 2);

                text = sb.ToString();
            }
            //Chop
            else if (text.Length > width)
                text = text.Remove(width);

            return text;
        }

        public static StringBuilder BuildString(string text, int lineWidth = 60)
        {
            List<string> lines;
            lines = new List<string>();

            string[] lineArray = text.Split("\r\n".ToArray(), StringSplitOptions.RemoveEmptyEntries);


            StringBuilder line = new StringBuilder();


            foreach (string arrayLine in lineArray)
            {
                string[] wordArray = arrayLine.Split(' ');
                foreach (string word in wordArray)
                {
                    Wrap(lines, line, word, lineWidth);
                }
                lines.Add(line.ToString());
                line.Clear();
            }

            StringBuilder output;
            output = new StringBuilder();
            foreach (string l in lines)
            {
                output.Append(l);
                output.Append("\r\n");
            }

            return output;
        }

        private static void Wrap(List<string> lines, StringBuilder line, string word, int lineWidth)
        {
            if (line.Length + word.Length >= lineWidth)
            {
                lines.Add(line.ToString());
                line.Clear();
                line.Append(word + " ");
            }
            else
                line.Append(word + " ");
        }

        public void Flash(Tile tile, int number = 10 ,long delay = 100)
        {
            long Timer;


            
            for (int i = 0; i < number; i++)
            {
                if (tile.Color == ConsoleColor.Red)
                    tile.Color = ConsoleColor.White;
                else
                    tile.Color = ConsoleColor.Red;

                DungeonManager.Instance.ForceRedraw();

                //This code belongs in a method in the GameManger or a future Time Manager
                Timer = GameManager.Instance.Time.ElapsedMilliseconds + delay;
                while (Timer > GameManager.Instance.Time.ElapsedMilliseconds)
                { 
                //wait 
                }
            }
        }

        public void ForceFullVisualization(DungeonLevel dungeonLevel)
        {
            Console.Clear();
            Camera.Layer.ClearOldSquares();
            GameManager.Instance.DungeonScreen.ReDraw();
            Visualize(dungeonLevel,true);
        }

        private void Draw(DungeonLevel dungeonLevel, Point startPoint)
        {
            Camera.Draw(dungeonLevel,startPoint);
        }
        #endregion

    }
}
